/*
 * Copyright (c) 2022 PATEO CONNECT+ (Nanjing) Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "voice_assistant_client_manager.h"
#include "voice_assistant_log.h"
#include "common_utils.h"
#include "iservice_registry.h"

using namespace OHOS::CarVoiceAssistant::CommonUtils;

namespace OHOS {
namespace CarVoiceAssistant {

#define CHECK_PROXY_VALID()                                     \
    if (CreateAbilityAgentProxy() == NULL) {                    \
        VOICE_ASSISTANT_LOGI("CreateAbilityAgentProxy failed"); \
        return VOICE_ASSISTANT_ERR;                             \
    }

    sptr<VoiceAssistantClientManager> VoiceAssistantClientManager::instance_;
    std::mutex VoiceAssistantClientManager::instanceLock_;

    sptr<VoiceAssistantClientManager> VoiceAssistantClientManager::GetInstance()
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::GetInstance");
        if (instance_ == nullptr) {
            std::lock_guard<std::mutex> autoLock(instanceLock_);
            if (instance_ == nullptr) {
                VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::GetInstance");
                instance_ = new VoiceAssistantClientManager();
            }
        }
        return instance_;
    }

    VoiceAssistantClientManager::VoiceAssistantClientManager()
    {
        CreateAbilityAgentProxy();
    }

    VoiceAssistantClientManager::~VoiceAssistantClientManager()
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::~VoiceAssistantClientManager");
        instance_ = NULL;
    }

    void VoiceAssistantClientManager::SetEventTarget(sptr<VoiceAssistantEventTarget> eventTarget)
    {
        eventTarget_ = eventTarget;
    }

    sptr<VoiceAssistantEventTarget> VoiceAssistantClientManager::GetEventTarget()
    {
        return eventTarget_;
    }

    sptr<IVoiceAssistantAbilityAgent> VoiceAssistantClientManager::CreateAbilityAgentProxy()
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy");

        std::lock_guard<std::mutex> autoLock(createProxyLock_);

        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy Start");

        if (mAbilityManager_) {
            VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy isExist");
            return mAbilityManager_;
        }

        sptr<ISystemAbilityManager> systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
        if (systemAbilityManager == nullptr) {
            VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy systemAbilityManager is nullptr");
            return nullptr;
        }

        auto systemAbility = systemAbilityManager->GetSystemAbility(CAR_VOICE_ASSISTANT_SERVICE_SA_ID, "");
        if (systemAbility == nullptr) {
            VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy systemAbility is nullptr");
            return nullptr;
        }

        mAbilityManager_ = iface_cast<IVoiceAssistantAbilityAgent>(systemAbility);

        deathRecipient_ = new VoiceAssistantAgentProxyDeathRecipient();
        deathRecipient_->SetNotifyCb(std::bind(&VoiceAssistantClientManager::ResetAgentProxy, this));
        mAbilityManager_->AsObject()->AddDeathRecipient(deathRecipient_);

        RegisterCallback();

        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::VoiceAssistantAbilityAgentProxy finished");

        return mAbilityManager_;
    }

    void VoiceAssistantClientManager::ResetAgentProxy()
    {
        VOICE_ASSISTANT_LOGI("VoiceAssistantClientManager::ResetAgentProxy");
        if (mAbilityManager_ != nullptr && mAbilityManager_->AsObject() != nullptr) {
            mAbilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_);
        }
        mAbilityManager_ = nullptr;
    }

    int32_t VoiceAssistantClientManager::IsEnableWakeUp(bool& isEnable)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->IsEnableWakeUp(isEnable);
    }

    int32_t VoiceAssistantClientManager::EnableWakeUp()
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->EnableWakeUp();
    }

    int32_t VoiceAssistantClientManager::DisableWakeUp()
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->DisableWakeUp();
    }

    int32_t VoiceAssistantClientManager::IsRecognizing(bool& isRecognizing)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->IsRecognizing(isRecognizing);
    }

    int32_t VoiceAssistantClientManager::StartRecognize(CommonUtils::VoiceAssistantErrorCode& result)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->StartRecognize(result);
    }

    int32_t VoiceAssistantClientManager::StopRecognize()
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->StopRecognize();
    }

    int32_t VoiceAssistantClientManager::PlayTTS(CommonUtils::VoiceAssistantErrorCode& result, std::string& tts)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->PlayTTS(result, tts);
    }

    int32_t VoiceAssistantClientManager::StopPlayTTS()
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->StopPlayTTS();
    }

    int32_t VoiceAssistantClientManager::RegisterHotwords(std::string& hotwords)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->RegisterHotwords(hotwords);
    }

    int32_t VoiceAssistantClientManager::SetCoord(double latitude, double longitude)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->SetCoord(latitude, longitude);
    }

    int32_t VoiceAssistantClientManager::RegisterCallback()
    { //由于在CreateAbilityAgentProxy调用，此处不需要CHECK_PROXY_VALID
        return mAbilityManager_->RegisterCallback();
    }

    int32_t VoiceAssistantClientManager::ChangeSpeakerType(std::string speaker)
    {
        CHECK_PROXY_VALID();
        return mAbilityManager_->ChangeSpeakerType(speaker);
    }

}
}